﻿using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Collections.Generic;

namespace SocketLib
{



	public class Client
	{
		private byte[] buff = new byte[1024*1024];//64K
		Socket socket;
		IPEndPoint ipe;

        object lockobj = new object();
        Queue<byte[]> bufferPool = new Queue<byte[]>();
        int i = 0;
		#region 事件委托
		public delegate void ConnectCallbackDelegate();
		public event ConnectCallbackDelegate ConnectCallbackEventHandler;
        public delegate void CallbackDelegate(object sender, CallbackEventArgs e);
        public event CallbackDelegate Callback_EventHandler;
        public class CallbackEventArgs : EventArgs
        {
            //public IPMPack pack { get; set; }
            public byte[] buffer { get; set; }

        }

		public delegate void ReceiveDelegate(object sender, ReceiveEventArgs e);
		public event ReceiveDelegate ReceiveEventHandler;

		public class ReceiveEventArgs : EventArgs
		{
			public string msg { get; set; }
			public string ip { get; set; }
		}

		public class ConnectCallbackEventArgs : EventArgs
		{

			public string msg { get; set; }
			public string ip { get; set; }
		}





		#endregion

		public void Connect(string host,int port)
		{
			//int port = 3451;
			//string host = "172.29.226.77";
			IPAddress ip = IPAddress.Parse(host);
			ipe = new IPEndPoint(ip, port);
			socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
			socket.BeginConnect(ipe, new AsyncCallback(ConnectCallback), socket);
            socket.BeginReceive(buff, 0, buff.Length, SocketFlags.None, new AsyncCallback(Receive2), socket);


            ThreadPool.QueueUserWorkItem(new WaitCallback(AnalysisbufferPool5));

		}

		#region SendMsg
		public void Send(string data)
		{
			byte[] byteData = System.Text.Encoding.ASCII.GetBytes(data);
			socket.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), socket);

		}

		public void SendMsg(string msg)
		{

			SendMsg(msg, 1);
		}

		public void SendMsg(string msg,int packType)
		{

			SendMsg(msg, 1,DateTime.Now.Millisecond);

		}

		public void SendMsg(string msg, int packType, int packNo)
		{

			byte[] data = Encoding.Default.GetBytes(msg);
			IPMPack sendIPMPack = new IPMPack();
			sendIPMPack.PackType = packType;
			//sendIPMPack.PackSize = data.Length;
			sendIPMPack.PackNo = packNo;
			sendIPMPack.Data = data;
			byte[] b = sendIPMPack.Packed();
			socket.BeginSend(b, 0, b.Length, 0, new AsyncCallback(SendCallback), socket);

		}

		#endregion

		#region SendFile

		public void SendFile(string path)
		{


		// FileStream fs = new FileStream("c:\\1.mp3", FileMode.Open);
		//byte[] tmpbyte = new byte[fs.Length ];
		//int count=fs.Read(tmpbyte,0,1024);
		//int tmpIndex=0;
		//while(count!=0)
		//{
		//tmpIndex=(tmpIndex+1)*102……
		//}
					

			FileInfo fi = new FileInfo(path);
			FileStream fs = fi.OpenRead();
			byte[] bytes = new byte[fs.Length];
			fs.Read(bytes, 0, Convert.ToInt32(fs.Length));
			fs.Close();

			//buff=new byte[bytes.Length];
			//先发文件名字和大小
			SendMsg(fi.Name + ":" +bytes.Length.ToString(), 2, 10000);
			//socket.Close();
			int size = bytes.Length;
			int sendsum = 0, offset = 0;


			int count = size / buff.Length;

			if (size % buff.Length != 0)
				count++;

			while (sendsum < count)
			{

				if (offset + buff.Length > bytes.Length)
				{
					buff = new byte[bytes.Length-offset];
				}

				Buffer.BlockCopy(bytes, offset, buff, 0, buff.Length);
				offset += buff.Length;
				sendsum++;


				IPMPack sendIPMPack = new IPMPack();
				sendIPMPack.PackType = 3;
				sendIPMPack.PackNo = 10000;
				sendIPMPack.Data = buff;
				byte[] b = sendIPMPack.Packed();

				socket.BeginSend(b, 0, b.Length, 0, new AsyncCallback(SendCallback), socket);
				

			}


		

		}

		public void SendFile2(string path)
		{




			FileInfo fi = new FileInfo(path);
			FileStream fs = fi.OpenRead();
			byte[] bytes = new byte[fs.Length];
			fs.Read(bytes, 0, Convert.ToInt32(fs.Length));
			fs.Close();

			//先发文件名字和大小
			    SendMsg(fi.Name + ":" + bytes.Length.ToString(), 2, 10000);

				IPMPack sendIPMPack = new IPMPack();
				sendIPMPack.PackType = 3;
				sendIPMPack.PackNo = 10000;
				sendIPMPack.Data = bytes;
				byte[] b = sendIPMPack.Packed();

				socket.BeginSend(b, 0, b.Length, 0, new AsyncCallback(SendCallback), socket);


			



		}

		public void SendImage(byte[] bytes)
		{

			//socket.Close();
			int size = bytes.Length;
			int sendsum = 0, offset = 0;


			int count = size / buff.Length;

			if (size % buff.Length != 0)
				count++;

			while (sendsum < count)
			{

				if (offset + buff.Length > bytes.Length)
				{
					buff = new byte[bytes.Length - offset];
				}

				Buffer.BlockCopy(bytes, offset, buff, 0, buff.Length);
				offset += buff.Length;
				sendsum++;


				IPMPack sendIPMPack = new IPMPack();
				sendIPMPack.PackType = 4;
				sendIPMPack.PackNo = 10000;
				sendIPMPack.Data = buff;
				byte[] b = sendIPMPack.Packed();

				socket.BeginSend(b, 0, b.Length, 0, new AsyncCallback(SendCallback), socket);


			}
		}

		#endregion 


		private void SendCallback(System.IAsyncResult ar)
		{
			try
			{
				Socket client = (Socket)ar.AsyncState;
				int bytesSend = client.EndSend(ar);
				//Console.WriteLine("Send {0} bytes to server.", bytesSend);
			}
			catch (Exception ex)
			{
				//MessageBox.Show(ex.Message.ToString());
			}

		}


		private void ConnectCallback(IAsyncResult e)
		{
			if (ConnectCallbackEventHandler != null)
			{
				ConnectCallbackEventHandler();

			}
		
			Socket client = (Socket)e.AsyncState;
			//client.EndConnect(e);
			client.BeginReceive(buff, 0, buff.Length, SocketFlags.None, new AsyncCallback(Receive2), client);


		}

		private void Receive(IAsyncResult ar)
		{

			Socket list = (Socket)ar.AsyncState;
			if (list.Connected)
			{


				IPEndPoint ep = (IPEndPoint)list.RemoteEndPoint;
				int len = list.EndReceive(ar);
				if (len > 0)
				{
					//收到消息
					if (ReceiveEventHandler != null)
					{
						ReceiveEventArgs args = new ReceiveEventArgs();
						args.ip = ep.Address.ToString();
						args.msg = Encoding.UTF8.GetString(buff, 0, len);
						ReceiveEventHandler(this, args);
					}
					list.BeginReceive(buff, 0, buff.Length, SocketFlags.None, new AsyncCallback(Receive), list);
				}
			}
		}

        private void Receive2(IAsyncResult ar)
        {
            Socket client = (Socket)ar.AsyncState;
            try
            {

                int revCount = client.EndReceive(ar);

                //int a = client.Available;

                if (revCount > 0)
                {
                    Byte[] a = new Byte[revCount];
                    Buffer.BlockCopy(buff, 0, a, 0, revCount);
                    bufferPool.Enqueue(a);
                    i = i + revCount;
                }
                //AnalysisbufferPool5(null);
                client.BeginReceive(buff, 0, buff.Length, SocketFlags.None, new AsyncCallback(Receive2), client);

            }
            catch (SocketException ex)
            {
                if (ex.ErrorCode == 10054)
                {
                    //throw new SocketLib.ex.ClientClosedException(ex.Message);
                   // Disconnect(client);

                }
            }
            finally
            {

            }
        }


		public void Closed()
		{
			socket.Close();
		}

		public long GetNo()
		{
			return DateTime.Now.ToFileTime();
		}

        /// <summary>
        /// 目前这个解析最快
        /// </summary>
        /// <param name="o"></param>
        public void AnalysisbufferPool5(object o)
        {

            int LenghHeader = 0; //定义收到包的长度

            bool needReadLengthHeader = true; //是否需要读取长度的头


            byte[] tempBuffer = null;

            while (true)
            {
                if (bufferPool.Count == 0)
                    continue;

                byte[] b1 = bufferPool.Dequeue();

                tempBuffer = MergeBytes(tempBuffer, b1);


                if (needReadLengthHeader)
                {
                    LenghHeader = BitConverter.ToInt32(tempBuffer, 0);
                    needReadLengthHeader = false;

                }



                //接收多了把多的放到缓存区
                if (tempBuffer.Length >= LenghHeader)
                {

                    needReadLengthHeader = true;


                    Byte[] a = new Byte[tempBuffer.Length - LenghHeader];
                    Buffer.BlockCopy(tempBuffer, LenghHeader, a, 0, tempBuffer.Length - LenghHeader);

                    //把完整的包发过去处理
                    if (Callback_EventHandler != null)
                    {
                        CallbackEventArgs args = new CallbackEventArgs();
                        byte[] ss = new byte[LenghHeader];
                        Buffer.BlockCopy(tempBuffer, 0, ss, 0, LenghHeader);
                        args.buffer = ss;
                        Callback_EventHandler(this, args);
                    }
                    tempBuffer = a;
                    ///TODO:如果这个是最后一个包 没发啊 
                    if (bufferPool.Count == 0 && tempBuffer.Length > 0)
                    {
                        if (Callback_EventHandler != null)
                        {
                            CallbackEventArgs args = new CallbackEventArgs();
                            args.buffer = tempBuffer;
                            Callback_EventHandler(this, args);
                        }
                        tempBuffer = null;
                    }



                }


            }
        }

        public byte[] MergeBytes(byte[] pByteA, byte[] pByteB)
        {
            if (pByteA == null || pByteA.Length == 0)
            {
                return pByteB;
            }
            else
            {

                MemoryStream ms = new MemoryStream();
                ms.Write(pByteA, 0, pByteA.Length);
                ms.Write(pByteB, 0, pByteB.Length);


                //return ms.GetBuffer();
                return ms.ToArray();
            }
        }

	}
}


